using BlazorAdmin.Models;
using BlazorAdmin.Interface;
using BootstrapBlazor.Components;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using Pangeo.Admin.Models;
using BlazorAdmin.Services.DbService;
using BlazorAdmin.Models.Dto;

namespace BlazorAdmin.Services
{
    /// <summary>
    /// Device 服务
    /// </summary>
    public class DeviceService : BaMgmtDbService, IDevice
    {
        public DeviceService(IPetaPoco db) : base(db) { }

        public async Task InsertOrUpdate(Device entity)
        {
            using var db = Create();
            var prvEntity = db.FirstOrDefault<Device>($"Where Guid = @0", entity.Guid);
            if (prvEntity == null)
            {
                entity.Status = EnumStatus.Normal.ToString();
                entity.Updater = "tcp";
                entity.UpdateTime = DateTime.Now;
                await db.InsertAsync(entity);
            }
            else // 选择性更新
            {
                bool isUpdate = false;

                if (!string.IsNullOrEmpty(entity.IP) && prvEntity.IP != entity.IP)
                {
                    prvEntity.IP = entity.IP;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.OS) && prvEntity.OS != entity.OS)
                {
                    prvEntity.OS = entity.OS;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.Mac) && prvEntity.Mac != entity.Mac)
                {
                    prvEntity.Mac = entity.Mac;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.Host) && prvEntity.Host != entity.Host)
                {
                    prvEntity.Host = entity.Host;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.Location) && prvEntity.Location != entity.Location)
                {
                    prvEntity.Location = entity.Location;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.Version) && prvEntity.Version != entity.Version)
                {
                    prvEntity.Version = entity.Version;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.AssetNo) && prvEntity.AssetNo != entity.AssetNo)
                {
                    prvEntity.AssetNo = entity.AssetNo;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.BackupDir) && prvEntity.BackupDir != entity.BackupDir)
                {
                    prvEntity.BackupDir = entity.BackupDir;
                    isUpdate = true;
                }
                if (!string.IsNullOrEmpty(entity.UploadPath) && prvEntity.UploadPath != entity.UploadPath)
                {
                    prvEntity.UploadPath = entity.UploadPath;
                    isUpdate = true;
                }

                if (isUpdate)
                {
                    prvEntity.Status = EnumStatus.Normal.ToString();
                    prvEntity.Updater = "tcp";
                    prvEntity.UpdateTime = DateTime.Now;

                    await db.UpdateAsync(prvEntity);
                }
            }
        }

        public async Task<bool> BatchDelete(List<int> deviceIds)
        {
            var strSql = $"delete from DeviceOrg where DeviceID in({string.Join(",", deviceIds)});";

            return await Create().ExecuteAsync(strSql) > 0;
        }

        public async Task<bool> BatchInsert(string orgCode, List<int> deviceIds)
        {
            // 一个设备只能关联一个组织，一个组织可以有多个设备
            var strSql = $"delete from DeviceOrg where DeviceID in({string.Join(",", deviceIds)});";
            strSql += "insert into DeviceOrg (DeviceID, OrgCode) values ";
            deviceIds.ForEach(device_id => strSql += $"({device_id}, '{orgCode}'),");
            strSql = strSql.Remove(strSql.Length - 1) + ";";

            return await Create().ExecuteAsync(strSql) > 0;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        public Task<QueryData<Device>> Query(AppQueryOption<string> query)
        {
            // 默认根据分组查询
            var strSql = string.Empty;

            switch (query.Param?.ToLower())
            {
                case "default": // 查询未分组的
                    strSql = $@"select * from Devices where status = '{EnumStatus.Normal.ToString()}' 
                                and id not in(select distinct(DeviceID) from DeviceOrg)";
                    break;
                case "custome_search": // 快速搜索、高级搜索
                    strSql = @$"select dev.*, org.OrgName from Devices dev
                                left join DeviceOrg dev_org on dev.id = dev_org.DeviceID
                                left join Organizes org on dev_org.OrgCode = org.OrgCode
                                where dev.status = '{EnumStatus.Normal.ToString()}'";

                    if (!string.IsNullOrWhiteSpace(query.Option.SearchText)) // 快速搜索
                    {
                        var searchTxt = $"'%{query.Option.SearchText.Trim()}%'";
                        if (query.Option.SearchText.Contains(".")) // IP
                            strSql += $" and dev.ip like {searchTxt}";
                        else if (query.Option.SearchText.Contains("-")) // MAC
                            strSql += $" and dev.mac like {searchTxt}";
                        else // Host or OS
                            strSql += $" and dev.host like {searchTxt} or dev.os like {searchTxt}";
                    }
                    else if (query.Option.SearchModel != null) // 高级搜索
                    {
                        var param = (DeviceInfo)query.Option.SearchModel;
                        if (param != null)
                        {
                            if (!string.IsNullOrEmpty(param.guid))
                                strSql += $" and dev.guid = '{param.guid}'";
                            if (!string.IsNullOrEmpty(param.ip))
                                strSql += $" and dev.ip like '%{param.ip}%'";
                            if (!string.IsNullOrEmpty(param.mac))
                                strSql += $" and dev.mac like '%{param.mac}%'";
                            if (!string.IsNullOrEmpty(param.host))
                                strSql += $" and dev.host like '%{param.host}%'";
                            if (!string.IsNullOrEmpty(param.location))
                                strSql += $" and dev.location like '%{param.location}%'";
                            if (!string.IsNullOrEmpty(param.version))
                                strSql += $" and dev.version like '%{param.version}%'";
                        }
                    }

                    strSql += " order by org.OrgName, dev.ip";
                    break;
                default: // 查询已分组的
                    strSql = @$"with recursive subtree(org_code, parent_orgcode) as (
	                                select OrgCode, ParentOrgCode from Organizes where OrgCode = '{query.Param}'
	                                union all
	                                select OrgCode, ParentOrgCode from Organizes
	                                join subtree on ParentOrgCode = subtree.org_code
                                )
                                select dev.*, org.OrgName from Devices dev
                                left join DeviceOrg dev_org on dev.id = dev_org.deviceid
                                left join Organizes org on dev_org.orgcode = org.OrgCode
                                where dev.status = '{EnumStatus.Normal.ToString()}' and org.OrgCode in (select subtree.org_code from subtree) order by org.OrgName desc, dev.ip";
                    break;
            }

            query.Sql = new(strSql);

            if (query.Option != null)
            {
                return PageQueryAsync<Device>(query);
            }
            else
            {
                var data = new QueryData<Device>();
                data.Items = Create().Query<Device>(strSql).ToList();

                return Task.FromResult(data);
            }
        }

        public async Task<string> GetGuid(string device_mac)
        {
            using var db = Create();
            var guid = db.FirstOrDefault<string>("select guid from devices where mac = @0", device_mac);

            return guid;
        }

        #region 默认生成的代码

        /// <summary>
        /// 保存、更新
        /// </summary>
        /// <param name="entity">实体对象</param>
        /// <returns>错误消息</returns>
        public async Task<string> Save(Device entity)
        {
            using var db = Create();
            bool isUpdate = entity.ID > 0;

            try
            {
                if (isUpdate)
                {
                    //var prvEntity = db.FirstOrDefault<Device>($"where id = {entity.id}");

                    //禁止更新以下字段
                    //entity.creator = prvEntity.creator;
                    //entity.createtime = prvEntity.createtime;

                    db.Update(entity);
                }
                else
                {
                    db.Insert(entity);
                }
            }
            catch (Exception ex)
            {
                return $"保存出错，{ex.Message}";
            }

            return string.Empty;
        }

        /// <summary>
        /// 获取实例
        /// </summary>
        /// <param name="id">主键id</param>
        /// <returns>实例对象</returns>
        public async Task<Device> Get(int id)
        {
            using var db = Create();
            var entity = db.FirstOrDefault<Device>("where id = @0", id);

            return entity;
        }

        /// <summary>
        /// 逻辑删除实例
        /// </summary>
        /// <param name="ids">主键id集合</param>
        /// <param name="curUser">当前用户</param>
        /// <returns></returns>
        public async Task<bool> Remove(List<int> ids, string curUser)
        {
            var strSql = $"set status = @0, updater = @1, updatetime = now() where id in ({string.Join(",", ids)})";
            using var db = Create();
            var rows = db.Update<Device>(strSql, SysEnumStatus.del.ToString(), curUser);

            return rows > 0;
        }

        /// <summary>
        /// 物理删除实例
        /// </summary>
        /// <param name="ids">主键id集合</param>
        /// <returns></returns>
        public async Task<bool> Delete(List<int> ids)
        {
            using var db = Create();
            var rows = db.Delete<Device>($"where id in ({string.Join(",", ids)})");

            return rows > 0;
        }

        #endregion
    }
}
